﻿#ifndef JSQLDATAMGR_H
#define JSQLDATAMGR_H

#include "jsql_global.h"
#include <QVariant>
#include "jsqlcustomtype.h"

// - class JSqlDataMgrs -

class JSqlDataMgrPrivate;

/**
 * @brief The JSqlDataMgr class, 数据记录管理类
 */
class JSQL_EXPORT JSqlDataMgr
{
public:

    /**
     * @brief transaction
     * @return
     */
    bool transaction();

    /**
     * @brief commit
     * @return
     */
    bool commit();

    /**
     * @brief rollback
     * @return
     */
    bool rollback();

    /**
     * @brief executeSql
     * @param query
     * @return
     */
    bool executeSql(const QString &query);

    /**
     * @brief existsTable, 查询指定表名是否存在于数据库中
     * @param tableName, 表名
     * @return, true：存在；false：不存在
     */
    bool existsTable(const QString &tableName) const;

    /**
     * @brief createSignalTable, 创建信号表
     * @param tableName, 表名
     * @return, true：创建成功；false：创建失败
     */
    bool createSignalTable(const QString &tableName);

    /**
     * @brief createRecordTable, 创建数据记录表
     * @param tableName, 表名
     * @param varNames, 变量名列表
     * @return, true：创建成功；false：创建失败
     */
    bool createRecordTable(const QString &tableName, const QStringList &varNames);

    /**
     * @brief createSignalTable, 创建热点范围表
     * @param tableName, 表名
     * @return, true：创建成功；false：创建失败
     */
    bool createHotSpotTable(const QString &tableName);

    /**
     * @brief addMainTableData, 添加一行主表数据
     * @param data, 数据
     * @return, true：添加成功；false：添加失败
     */
    bool addMainTableData(const stMainTableInfo &data);

    /**
     * @brief removeMainTableData
     * @param info
     * @return
     */
    bool removeMainTableData(const JFileNameInfo &info);

    /**
     * @brief existsMainTable, 查询指定主表是否已存在指定批次的数据
     * @param info, 表信息
     * @return, true：已存在；false：不存在
     */
    bool existsMainTable(const JFileNameInfo &info) const;

    /**
     * @brief readMainTable, 查询指定主表是否已存在指定批次的数据
     * @param info, 表信息[in]
     * @param DYXHB, 对应信号表[out]
     * @param DYZB, 对应值表[out]
     * @return, true：读取成功；false：读取失败
     */
    bool readMainTable(const JFileNameInfo &info, QString &DYXHB, QString &DYZB);

    /**
     * @brief addMainTableData, 添加多行主表数据
     * @param data, 数据
     * @return, true：添加成功；false：添加失败
     */
    bool addMainTableData(const QList<stMainTableInfo> &data);

    /**
     * @brief readMainTableBySection
     * @param sectionName
     * @param sectionValue
     * @param info
     * @return
     */
    bool readMainTableBySection(const QString &sectionName,
                                const QString &sectionValue,
                                stMainTableInfo &info);

    /**
     * @brief readSignalTableName, 获取指定信号表名
     * @param info, 信号表信息
     * @return, true：获取成功；false：获取失败
     */
    bool readSignalTableName(const JFileNameInfo &info);

    /**
     * @brief addSignalData, 添加一行信号表数据
     * @param tableName, 表名
     * @param data, 数据
     * @param update, true：更新存在的信号；false：不更新存在的信号
     * @return, true：添加成功；false：添加失败
     */
    bool addSignalData(const QString &tableName, const stSignalInfo &data,
                       bool isIgnoreSift, bool update = false);

    /**
     * @brief addSignalData, 添加多行信号表数据
     * @param tableName, 表名
     * @param data, 数据
     * @return, true：添加成功；false：添加失败
     */
    bool addSignalData(const QString &tableName, const QList<stSignalInfo> &data,
                       bool isIgnoreSift);

    /**
     * @brief readSignalData, 读取指定信号表的所有记录
     * @param tableName, 信号表
     * @param data, 读取的数据
     * @return, true：读取成功；false：读取失败
     */
    bool readSignalData(const QString &tableName, QList<stSignalInfo> &data) const;

    /**
     * @brief readAllSignalData
     * @param tableName
     * @param data
     * @return
     */
    bool readAllSignalData(const QString &tableName, QList<stSignalInfo> &data) const;

    /**
     * @brief readSignalDataTime
     * @param tableName
     * @param data
     * @return
     */
    bool readSignalDataTime(const QString &tableName, stSignalInfo &data) const;

    /**
     * @brief readSignalData, 读取指定信号表的所有记录
     * @param info, 信号表信息
     * @param data, 读取的数据
     * @param hasTime, 包含时间信号列
     * @return, true：读取成功；false：读取失败
     */
    bool readSignalData(const JFileNameInfo &info, QList<stSignalInfo> &data,
                        bool hasTime) const;

    /**
     * @brief updateSignalSift
     * @param tableName
     * @param mapSignalSift
     * @return
     */
    bool updateSignalSift(const QString &tableName, const QMap<QString, bool> &mapSignalSift);

    /**
     * @brief addRecordData, 添加一行值表数据
     * @param tableName, 表名
     * @param valuesString, 一行序列化数据
     * @return, true：添加成功；false：添加失败
     */
    bool addRecordData(const QString &tableName, const QString &valuesString);

    /**
     * @brief addRecordData, 添加多行值表数据
     * @param tableName, 表名
     * @param time, 时间
     * @param values, 值
     * @return, true：添加失败；false：添加成功
     */
    bool addRecordData(const QString &tableName, const QTime &time, const QList<double> &values);

    /**
     * @brief addRecordData, 添加一行值表数据
     * @param tableName, 表名
     * @param columnsString, 序列化列名
     * @param valuesString, 序列化值
     * @return, true：添加成功；false：添加失败
     */
    bool addRecordData(const QString &tableName, const QString &columnsString, const QString &valuesString);

    /**
     * @brief addRecordData, 添加多行值表数据
     * @param tableName, 表名
     * @param columnsString, 序列化列名
     * @param time, 时间
     * @param values, 值
     * @return, true：添加成功；false：添加失败
     */
    bool addRecordData(const QString &tableName, const QString &columnsString,
                       const QTime &time, const QList<double> &values);

    /**
     * @brief addRecordData, 添加多行值表数据
     * @param tableName, 表名
     * @param sigs, 列名
     * @param valuesString, 对应序列化值
     * @return
     */
    bool addRecordData(const QString &tableName, const QStringList &sigs, const QString &valuesString);

    /**
     * @brief addRecordData, 添加多行值表数据
     * @param tableName, 表名
     * @param sigs, 列名
     * @param time, 时间
     * @param values, 值
     * @return, true：添加成功；false：添加失败
     */
    bool addRecordData(const QString &tableName, const QStringList &sigs,
                       const QTime &time, const QList<double> &values);

    /**
     * @brief addHotSpotData
     * @param tableName
     * @param range
     * @return
     */
    bool addHotSpotData(const QString &tableName, const QRectF &range);

    /**
     * @brief signalColumnNames, 获取信号表所有列名称（按顺序）
     * @param tableName, 信号表名称
     * @param sift, true：只获取选中项；false：获取所有列
     * @return, 列名称列表
     */
    QStringList signalColumnNames(const QString &tableName, bool sift = true) const;

    /**
     * @brief readSignalData
     * @param info
     * @return
     */
    QStringList readSignalData(const JFileNameInfo &info, bool sift = true) const;

    /**
     * @brief mainTableName, 获取主表名称
     * @return, 主表名称
     */
    static QString mainTableName();

    /**
     * @brief signalTableNamePrefix, 获取信号表名称固定前缀
     * @return, 信号表名称前缀
     */
    static QString signalTableNamePrefix();

    /**
     * @brief recordTableNamePrefix, 获取值表名称固定前缀
     * @return, 值表名称前缀
     */
    static QString recordTableNamePrefix();

    /**
     * @brief hotSpotTableNamePrefix,
     * @return
     */
    static QString hotSpotTableNamePrefix();

    ///! read

    /**
     * @brief readAllJX
     * @return
     */
    QStringList readAllJX() const;

    /**
     * @brief readAllJH
     * @return
     */
    QStringList readAllJH() const;

    /**
     * @brief readAllRQ
     * @return
     */
    QList<QDate> readAllRQ() const;

    /**
     * @brief readAllJC
     * @return
     */
    QList<int> readAllJC() const;

    /**
     * @brief readAllJCAsString
     * @return
     */
    QStringList readAllJCAsString() const;

    /**
     * @brief readAllJC, 读取给定条件的所有架次数据
     * @param JX, 机型
     * @param JH, 机号
     * @param RQ, 日期
     * @return, 读取到的数据
     */
    QList<int> readAllJC(const QString &JX, const QString &JH,
                         const QDate &RQ) const;

    /**
     * @brief readAllJCAsString, 读取给定条件的所有架次数据（以字符串形式返回）
     * @param JX, 机型
     * @param JH, 机号
     * @param RQ, 日期
     * @return, 读取到的数据
     */
    QStringList readAllJCAsString(const QString &JX, const QString &JH,
                                  const QDate &RQ) const;

    /**
     * @brief readAllSignalTableName
     * @return
     */
    QStringList readAllSignalTableName() const;

    ///! 读取主表数据

    /**
     * @brief readSubTableSuffix, 读取对应信号表和值表名称
     * @param JX, 机型（非空有效）
     * @param JH, 机号（非空有效）
     * @param RQ, 日期（非空有效）
     * @param JC, 架次（大于0有效）
     * @param suffixes, 返回的信号表和值表
     * @return, true：读取成功；false：读取失败
     */
    bool readSubTableSuffix(const QString &JX,
                            const QString &JH,
                            const QString &RQ,
                            int JC,
                            QStringList &suffixes) const;

    /**
     * @brief readSubTableSuffix
     * @param fileNameInfo
     * @param suffixes
     * @return
     */
    bool readSubTableSuffix(const JFileNameInfo &fileNameInfo,
                            QStringList &suffixes) const;

    ///! 读取信号表数据

    /**
     * @brief readSignalTableColumnName, 读取指定信号表的列名称（如果别名为空，则用原信号名替代）
     * @param tableName, 信号表名
     * @return, 列名称
     */
    QStringList readSignalTableColumnName(const QString &tableName, bool sift = true) const;

    /**
     * @brief readSignalTableColumnSymbol
     * @param tableName
     * @param sift
     * @return
     */
    QStringList readSignalTableColumnSymbol(const QString &tableName, bool sift = true) const;

    ///! 读取值表数据

    /**
     * @brief readRecordData, 读取指定值表数据
     * @param tableName, 值表表名称
     * @param data, 读取到的数据
     * @return, true：读取成功；false：读取失败
     */
    bool readRecordData(const QString &tableName, QVector<QVector<QVariant> > &data);

    /**
     * @brief readRecordData
     * @param tableName
     * @param data
     * @param rowOffset
     * @param rowCount
     * @param orderSection
     * @return
     */
    bool readRecordData(const QString &tableName,
                        QList<QVariantList> &data,
                        const QStringList &symbols,
                        int rowOffset, int rowCount,
                        const QString &orderSection);

    /**
     * @brief readRecordData, 读取任意个字段的所有数据
     * @param tableName, 表名
     * @param sectionNames, 字段表
     * @param data, 读取的数据
     * @return, true：读取成功；false：读取失败
     */
    bool readRecordData(const QString &tableName,
                        const QStringList sectionNames,
                        QVector<QVector<QVariant> > &data);

    /**
     * @brief readRecordData, 读取给定两个字段的所有数据
     * @param tableName, 表名
     * @param section1, 字段1名称
     * @param section2, 字段2名称
     * @param data, 读取的数据
     * @return, true：读取成功；false：读取失败
     */
    bool readRecordData(const QString &tableName,
                        const QString &section1,
                        const QString &section2,
                        QVector<QPointF> &data);

    /**
     * @brief readRecordData
     * @param tableName
     * @param section1
     * @param section2
     * @param range
     * @param data
     * @return
     */
    bool readRecordData(const QString &tableName,
                        const QString &section1,
                        const QString &section2,
                        const QRectF &range,
                        QVector<QPointF> &data);

    /**
     * @brief readRecordData
     * @param tableName
     * @param section1
     * @param section2
     * @param sectionTime
     * @param sectionValue
     * @param range
     * @param datad
     * @return
     */
    bool readRecordData(const QString &tableName,
                        const QString &section1,
                        const QString &section2,
                        const QString &sectionTime,
                        const QString &sectionValue,
                        const QRectF &range,
                        QVector<QPointF> &data);

    /**
     * @brief readRecordDataV
     * @param tableName
     * @param section1
     * @param section2
     * @param sectionX
     * @param sectionValue
     * @param range
     * @param data
     * @return
     */
    bool readRecordDataV(const QString &tableName,
                         const QString &section1,
                         const QString &section2,
                         const QString &sectionX,
                         const QString &sectionValue,
                         const QRectF &range,
                         QVector<QPointF> &data);

    /**
     * @brief readRecordData, 读取给定字段的所有数据（默认第一个字段为时间）
     * @param tableName, 表名
     * @param sectionTime, 时间字段名称
     * @param sectionValue, 信号字段名称
     * @param data, 读取的数据
     * @return, true：读取成功；false：读取失败
     */
    bool readRecordData(const QString &tableName,
                        const QString &sectionTime,
                        const QString &sectionValue,
                        QList<QPair<QTime, qreal> > &data);

    /**
     * @brief readRecordData, 读取给定字段指定范围的数据
     * @param tableName, 表名
     * @param section1, 字段1名称
     * @param section2, 字段2名称
     * @param range, 范围
     * @param data, 读取的数据
     * @return, true：读取成功；false：读取失败
     */
    bool readRecordData(const QString &tableName,
                        const QString &section1,
                        const QString &section2,
                        const QRectF &range,
                        QList<QPointF> &data);

    /**
     * @brief readRecordData, 读取给定字段指定范围的数据（默认第一个字段为时间）
     * @param tableName, 表名
     * @param sectionTime, 时间字段名称
     * @param sectionValue, 信号字段名称
     * @param range, 范围
     * @param data, 读取的数据
     * @return, true：读取成功；false：读取失败
     */
    bool readRecordData(const QString &tableName,
                        const QString &sectionTime,
                        const QString &sectionValue,
                        const QRectF &range,
                        QList<QPair<QTime, qreal> > &data);

    /**
     * @brief readRecordData
     * @param tableName
     * @param section1
     * @param sectionTime
     * @param sectionValue
     * @param range
     * @param data
     * @return
     */
    bool readRecordData(const QString &tableName,
                        const QString &section1,
                        const QString &sectionTime,
                        const QString &sectionValue,
                        const QRectF &range,
                        QList<QPair<QTime, qreal> > &data);

    /**
     * @brief readRecordDataV
     * @param tableName
     * @param section1
     * @param sectionX
     * @param sectionValue
     * @param range
     * @param data
     * @return
     */
    bool readRecordDataV(const QString &tableName,
                         const QString &section1,
                         const QString &sectionX,
                         const QString &sectionValue,
                         const QRectF &range,
                         QList<QPair<QTime, qreal> > &data);

    /**
     * @brief readRecordDataV
     * @param tableName
     * @param sectionX
     * @param sectionY
     * @param rangeSectionX
     * @param rangeSectionY
     * @param range
     * @param data
     * @return
     */
    bool readRecordDataV(const QString &tableName,
                         const QString &sectionX,
                         const QString &sectionY,
                         const QString &rangeSectionX,
                         const QString &rangeSectionY,
                         const QRectF &range,
                         QList<QPair<QTime, qreal> > &data);

    /**
     * @brief readRecordData
     * @param tableName
     * @param sectionTime
     * @param sectionValue
     * @param range
     * @param data
     * @return
     */
    bool readRecordData(const QString &tableName,
                        const QString &sectionTime,
                        const QString &sectionValue,
                        const QRectF &range,
                        QList<QVariantList> &data);

    /**
     * @brief readRecordDataV
     * @param tableName
     * @param sectionX
     * @param sectionValue
     * @param range
     * @param data
     * @return
     */
    bool readRecordDataV(const QString &tableName,
                         const QString &sectionX,
                         const QString &sectionValue,
                         const QRectF &range,
                         QList<QVariantList> &data);

    /**
     * @brief readRecordDataV
     * @param tableName
     * @param sectionX
     * @param sectionValue
     * @param range
     * @param symbols
     * @param data
     * @param rowOffset
     * @param rowCount
     * @param orderSection
     * @return
     */
    bool readRecordDataV(const QString &tableName,
                         const QString &sectionX,
                         const QString &sectionValue,
                         const QRectF &range,
                         const QStringList &symbols,
                         QList<QVariant> &data,
                         int rowOffset, int rowCount,
                         const QString &orderSection);

    /**
     * @brief rowCountOfRecordDataV
     * @param tableName
     * @param sectionX
     * @param sectionValue
     * @param range
     * @return
     */
    int rowCountOfRecordDataV(const QString &tableName,
                              const QString &sectionX,
                              const QString &sectionValue,
                              const QRectF &range);

    /**
     * @brief readRecordData
     * @param tableName
     * @param sections
     * @param sectionTime
     * @param sectionValue
     * @param range
     * @param data
     * @return
     */
    bool readRecordData(const QString &tableName,
                        const QStringList &sections,
                        const QString &sectionTime,
                        const QString &sectionValue,
                        const QRectF &range,
                        QList<QVariantList> &data);

    /**
     * @brief readRecordData
     * @param tableName
     * @param sectionTime
     * @param sectionValue
     * @param section1
     * @param range
     * @param range1
     * @return
     */
    bool readRecordData(const QString &tableName,
                        const QString &sectionTime,
                        const QString &sectionValue,
                        const QString &section1,
                        const QRectF &range,
                        QRectF &range1);

    /**
     * @brief readRecordData
     * @param fileNameInfo
     * @param sectionTime
     * @param sectionValue
     * @param section1
     * @param range
     * @param range1
     * @return
     */
    bool readRecordData(const JFileNameInfo &fileNameInfo,
                        const QString &sectionTime,
                        const QString &sectionValue,
                        const QString &section1,
                        const QRectF &range,
                        QRectF &range1);

    /**
     * @brief readRecordDataV
     * @param fileNameInfo
     * @param machSection
     * @param heightSection
     * @param sectionValue
     * @param rangeBase
     * @param range
     * @return
     */
    bool readRecordDataV(const JFileNameInfo &fileNameInfo,
                         const QString &machSection,
                         const QString &heightSection,
                         const QString &sectionValue,
                         const QRectF &rangeBase,
                         QPointF &range);

    /**
     * @brief readRecordDataV
     * @param tableName
     * @param machSection
     * @param heightSection
     * @param sectionValue
     * @param rangeBase
     * @param range
     * @return
     */
    bool readRecordDataV(const QString &tableName,
                         const QString &machSection,
                         const QString &heightSection,
                         const QString &sectionValue,
                         const QRectF &rangeBase,
                         QPointF &range);
    /**
     * @brief readRecordData
     * @param tableName
     * @param sectionBase
     * @param sectionTime
     * @param sectionValues
     * @param ranges
     * @param rangeBase
     * @return
     */
    bool readRecordData(const QString &tableName,
                        const QString &sectionBase,
                        const QString &sectionTime,
                        const QList<QPair<QString/*sectioinValue*/, QRectF/*range*/> > &ranges,
                        QRectF &rangeBase);

    /**
     * @brief readRecordData
     * @param fileNameInfo
     * @param sectionBase
     * @param sectionTime
     * @param ranges
     * @param rangeBase
     * @return
     */
    bool readRecordData(const JFileNameInfo &fileNameInfo,
                        const QString &sectionBase,
                        const QString &sectionTime,
                        const QList<QPair<QString/*sectioinValue*/, QRectF/*range*/> > &ranges,
                        QRectF &rangeBase);

    /**
     * @brief readRecordDataV
     * @param fileNameInfo
     * @param machSection
     * @param heightSection
     * @param mapRanges
     * @param range
     * @return
     */
    bool readRecordDataV(const JFileNameInfo &fileNameInfo,
                         const QString &machSection,
                         const QString &heightSection,
                         const QMap<QString/*sectioinValue*/, QPointF/*range*/> &mapRanges,
                         QRectF &range);

    /**
     * @brief readRecordDataV
     * @param mapRanges
     * @param range
     * @return
     */
    bool readRecordDataV(const QMap<QString/*suffix*/, QMap<QString/*symbol*/,QPointF/*range*/> > &mapRanges,
                         QRectF &range);

    /**
     * @brief readHotSpotData
     * @param tableName
     * @param ranges
     * @return
     */
    bool readHotSpotData(const QString &tableName,
                         QList<QRectF> &ranges);

    /**
     * @brief symbolOfName
     * @param info
     * @param name
     * @param symbol
     * @param sift
     * @return
     */
    bool symbolOfName(const JFileNameInfo &info, const QString &name, QString &symbol, bool sift = true);

    /**
     * @brief clearBaseLine
     */
    bool clearBaseLine();

    /**
     * @brief addBaseLine
     * @param groupsData
     * @return
     */
    bool addBaseLine(const QList<QVector<QPointF> > &groupsData);

    /**
     * @brief readBaseLine
     * @param groupsData
     * @return
     */
    bool readBaseLine(QList<QVector<QPointF> > &groupsData);

    /**
     * @brief readSignalAxisSection
     * @param info
     * @param axisXName
     * @param axisYName
     * @param axisXSection
     * @param axisYSection
     * @param sift
     * @return
     */
    bool readSignalAxisSection(const JFileNameInfo &info,
                               const QString &axisXName,
                               const QString &axisYName,
                               QString &axisXSection,
                               QString &axisYSection,
                               bool sift = true) const;

    /**
     * @brief readSignalAxisSection
     * @param tableName
     * @param axisXName
     * @param axisYName
     * @param axisXSection
     * @param axisYSection
     * @param sift
     * @return
     */
    bool readSignalAxisSection(const QString &tableName,
                               const QString &axisXName,
                               const QString &axisYName,
                               QString &axisXSection,
                               QString &axisYSection,
                               bool sift = true) const;

    /**
     * @brief readSignalAxisName
     * @param info
     * @param axisXSection
     * @param axisYSection
     * @param axisXName
     * @param axisYName
     * @param sift
     * @return
     */
    bool readSignalAxisName(const JFileNameInfo &info,
                            const QString &axisXSection,
                            const QString &axisYSection,
                            QString &axisXName,
                            QString &axisYName,
                            bool sift = true) const;

    /**
     * @brief readSignalAxisName
     * @param tableName
     * @param axisXSection
     * @param axisYSection
     * @param axisXName
     * @param axisYName
     * @param sift
     * @return
     */
    bool readSignalAxisName(const QString &tableName,
                            const QString &axisXSection,
                            const QString &axisYSection,
                            QString &axisXName,
                            QString &axisYName,
                            bool sift = true) const;

    /**
     * @brief deleteAllRecordData
     * @param info
     * @return
     */
    bool deleteAllRecordData(const JFileNameInfo &info);

    /**
     * @brief deleteRecordData
     * @param tableName
     * @param symbolTime
     * @param minimum
     * @param maximum
     * @param retain
     * @return
     */
    bool deleteRecordData(const QString &tableName,
                          const QString &symbolTime,
                          const QTime &minimum,
                          const QTime &maximum,
                          bool retain);

    /**
     * @brief conherenceRecordTable
     * @param tableName
     * @return
     */
    bool conherenceRecordTable(const QString &tableName);

    /**
     * @brief database
     * @return
     */
    void *database();

    /**
     * @brief removeRecordByJC
     * @param jcs
     * @return
     */
    bool removeRecordByJC(const QList<int> &jcs);

    /**
     * @brief removeTables
     * @param suffix
     * @return
     */
    bool removeTables(const QString &suffix);

private:
    JSqlDataMgr();
    ~JSqlDataMgr();

private:
    J_DECLARE_PRIVATE(JSqlDataMgr)
    J_DECLARE_SINGLE_INSTANCE(JSqlDataMgr)
};

#endif // JSQLDATAMGR_H
